package org.aman.generator.service;

import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.aman.generator.plugin.AmanPluginConfig;
import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.CompilationUnit;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.codegen.AbstractJavaGenerator;

/**
 * @desc <p></p>
 * @author DaiJiangGuo
 * @date 2015年5月12日下午12:28:04
 */
public class ServiceInterfaceGenerator extends AbstractJavaGenerator {
    private AmanPluginConfig apc;
    public ServiceInterfaceGenerator(AmanPluginConfig apc) {
        super();
        this.apc = apc;
        this.setContext(apc.context);
        this.setIntrospectedTable(apc.introspectedTable);
        initialized();
    }

    public void initialized() {
    }

    @Override
    public List<CompilationUnit> getCompilationUnits() {
        CommentGenerator commentGenerator = context.getCommentGenerator();

        Interface interfaze = new Interface(apc.serviceType);
        interfaze.setVisibility(JavaVisibility.PUBLIC);
        commentGenerator.addJavaFileComment(interfaze);

        if (stringHasValue(apc.serviceExtends)) {
            FullyQualifiedJavaType fqjt = new FullyQualifiedJavaType(apc.serviceExtends);
            interfaze.addImportedType(fqjt);
            
            List<IntrospectedColumn> pkCols = introspectedTable.getPrimaryKeyColumns();
            if(pkCols != null && pkCols.size() == 1){
                FullyQualifiedJavaType pkType = pkCols.get(0).getFullyQualifiedJavaType();
                interfaze.addImportedType(apc.modelType);
                interfaze.addImportedType(pkType);
                fqjt.addTypeArgument(new FullyQualifiedJavaType(pkType.getShortName()));
                fqjt.addTypeArgument(new FullyQualifiedJavaType(apc.modelType.getShortName()));
            } else {
                interfaze.addImportedType(apc.modelType);
                fqjt.addTypeArgument(new FullyQualifiedJavaType("Object"));
                fqjt.addTypeArgument(new FullyQualifiedJavaType(apc.modelType.getShortName()));
            }
            interfaze.addSuperInterface(new FullyQualifiedJavaType(fqjt.getShortName()));
        }

        if (apc.serviceMethod_gen_save) {
            addSaveMethod(interfaze, introspectedTable);
        }
        if (apc.serviceMethod_gen_saveSelective) {
            addSaveSelectiveMethod(interfaze, introspectedTable);
        }
        if (apc.serviceMethod_gen_deleteByPk) {
            addDeleteByPkMethod(interfaze, introspectedTable);
        }
        if (apc.serviceMethod_gen_updateByPk) {
            addUpdateByPkMethod(interfaze, introspectedTable);
        }
        if (apc.serviceMethod_gen_updateByPkSelective) {
            addUpdateByPkSelectiveMethod(interfaze, introspectedTable);
        }
        if (apc.serviceMethod_gen_findByPk) {
            addFindByPkMethod(interfaze, introspectedTable);
        }
        if (apc.serviceMethod_gen_queryByMap) {
            addQueryByMapMethod(interfaze, introspectedTable);
        }
        if (apc.serviceMethod_gen_queryByEntity) {
            addQueryByEntityMethod(interfaze, introspectedTable);
        }
        if (apc.serviceMethod_gen_queryByPager) {
            addQueryByPagerMethod(interfaze, introspectedTable);
        }

        List<CompilationUnit> answer = new ArrayList<CompilationUnit>();
        answer.add(interfaze);

        return answer;
    }
    /**
     * @author DaiJiangGuo
     * @data 2015年5月12日 上午11:15:11
     * @param interfaze
     * @param introspectedTable
     */
    private void addQueryByPagerMethod(Interface interfaze, IntrospectedTable introspectedTable) {
        Set<FullyQualifiedJavaType> importedTypes = new TreeSet<FullyQualifiedJavaType>();
        Method method = new Method();

        method.setVisibility(JavaVisibility.PUBLIC);
        FullyQualifiedJavaType returnType = apc.pagerType;
        method.setReturnType(returnType);
        importedTypes.add(returnType);
        method.setName(apc.serviceMethod_queryByPager);

        FullyQualifiedJavaType parameterType = apc.pagerType;

        importedTypes.add(parameterType);
        method.addParameter(new Parameter(parameterType, "pager")); //$NON-NLS-1$

        context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

        interfaze.addImportedTypes(importedTypes);
        interfaze.addMethod(method);
    }

    /**
     * @author DaiJiangGuo
     * @data 2015年5月12日 上午11:15:08
     * @param interfaze
     * @param introspectedTable
     */
    private void addQueryByEntityMethod(Interface interfaze, IntrospectedTable introspectedTable) {
        Set<FullyQualifiedJavaType> importedTypes = new TreeSet<FullyQualifiedJavaType>();
        Method method = new Method();

        method.setVisibility(JavaVisibility.PUBLIC);
        FullyQualifiedJavaType returnType = new FullyQualifiedJavaType("java.util.List<"+introspectedTable.getBaseRecordType()+">");
        method.setReturnType(returnType);
        importedTypes.add(returnType);
        method.setName(apc.serviceMethod_queryByEntity);

        FullyQualifiedJavaType parameterType = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType());

        importedTypes.add(parameterType);
        method.addParameter(new Parameter(parameterType, "entity")); //$NON-NLS-1$

        context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

        interfaze.addImportedTypes(importedTypes);
        interfaze.addMethod(method);

    }

    /**
     * @author DaiJiangGuo
     * @data 2015年5月12日 上午11:15:04
     * @param interfaze
     * @param introspectedTable
     */
    private void addQueryByMapMethod(Interface interfaze, IntrospectedTable introspectedTable) {
        Set<FullyQualifiedJavaType> importedTypes = new TreeSet<FullyQualifiedJavaType>();
        Method method = new Method();

        method.setVisibility(JavaVisibility.PUBLIC);
        FullyQualifiedJavaType returnType = new FullyQualifiedJavaType("java.util.List<"+introspectedTable.getBaseRecordType()+">");
        method.setReturnType(returnType);
        importedTypes.add(returnType);
        method.setName(apc.serviceMethod_queryByMap);

        FullyQualifiedJavaType parameterType = new FullyQualifiedJavaType("java.util.Map<String, Object>");

        importedTypes.add(parameterType);
        method.addParameter(new Parameter(parameterType, "paramMap")); //$NON-NLS-1$

        context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

        interfaze.addImportedTypes(importedTypes);
        interfaze.addMethod(method);

    }

    /**
     * @author DaiJiangGuo
     * @data 2015年5月12日 上午11:15:00
     * @param interfaze
     * @param introspectedTable
     */
    private void addUpdateByPkSelectiveMethod(Interface interfaze, IntrospectedTable introspectedTable) {
        Set<FullyQualifiedJavaType> importedTypes = new TreeSet<FullyQualifiedJavaType>();
        Method method = new Method();

        method.setVisibility(JavaVisibility.PUBLIC);
        method.setReturnType(new FullyQualifiedJavaType("int"));
        method.setName(apc.serviceMethod_updateByPkSelective);

        FullyQualifiedJavaType parameterType = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType());

        importedTypes.add(parameterType);
        method.addParameter(new Parameter(parameterType, "entity")); //$NON-NLS-1$

        context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

        interfaze.addImportedTypes(importedTypes);
        interfaze.addMethod(method);

    }

    /**
     * @author DaiJiangGuo
     * @data 2015年5月12日 上午11:14:57
     * @param interfaze
     * @param introspectedTable
     */
    private void addUpdateByPkMethod(Interface interfaze, IntrospectedTable introspectedTable) {
        Set<FullyQualifiedJavaType> importedTypes = new TreeSet<FullyQualifiedJavaType>();
        Method method = new Method();

        method.setVisibility(JavaVisibility.PUBLIC);
        method.setReturnType(new FullyQualifiedJavaType("int"));
        method.setName(apc.serviceMethod_updateByPk);

        FullyQualifiedJavaType parameterType = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType());

        importedTypes.add(parameterType);
        method.addParameter(new Parameter(parameterType, "entity")); //$NON-NLS-1$

        context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

        interfaze.addImportedTypes(importedTypes);
        interfaze.addMethod(method);

    }

    /**
     * @author DaiJiangGuo
     * @data 2015年5月12日 上午11:14:55
     * @param interfaze
     * @param introspectedTable
     */
    private void addDeleteByPkMethod(Interface interfaze, IntrospectedTable introspectedTable) {
        Set<FullyQualifiedJavaType> importedTypes = new TreeSet<FullyQualifiedJavaType>();
        Method method = new Method();

        method.setVisibility(JavaVisibility.PUBLIC);
        method.setReturnType(new FullyQualifiedJavaType("int"));
        method.setName(apc.serviceMethod_deleteByPk);

        List<IntrospectedColumn> pkCols = introspectedTable.getPrimaryKeyColumns();
        for(IntrospectedColumn pk : pkCols){
            FullyQualifiedJavaType paramPk = pk.getFullyQualifiedJavaType();
            importedTypes.add(paramPk);
            method.addParameter(new Parameter(paramPk, pk.getJavaProperty()));
        }

        context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

        interfaze.addImportedTypes(importedTypes);
        interfaze.addMethod(method);

    }

    /**
     * @author DaiJiangGuo
     * @data 2015年5月12日 上午11:14:52
     * @param interfaze
     * @param introspectedTable
     */
    private void addSaveSelectiveMethod(Interface interfaze, IntrospectedTable introspectedTable) {
        Set<FullyQualifiedJavaType> importedTypes = new TreeSet<FullyQualifiedJavaType>();
        Method method = new Method();

        method.setVisibility(JavaVisibility.PUBLIC);
        method.setReturnType(new FullyQualifiedJavaType(introspectedTable.getBaseRecordType()));
        method.setName(apc.serviceMethod_saveSelective);

        FullyQualifiedJavaType parameterType = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType());

        importedTypes.add(parameterType);
        method.addParameter(new Parameter(parameterType, "entity")); //$NON-NLS-1$

        context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

        interfaze.addImportedTypes(importedTypes);
        interfaze.addMethod(method);
    }

    /**
     * @author DaiJiangGuo
     * @data 2015年5月12日 上午11:14:47
     * @param interfaze
     * @param introspectedTable
     */
    private void addSaveMethod(Interface interfaze, IntrospectedTable introspectedTable) {
        Set<FullyQualifiedJavaType> importedTypes = new TreeSet<FullyQualifiedJavaType>();
        Method method = new Method();

        method.setVisibility(JavaVisibility.PUBLIC);
        method.setReturnType(new FullyQualifiedJavaType(introspectedTable.getBaseRecordType()));
        method.setName(apc.serviceMethod_save);

        FullyQualifiedJavaType parameterType = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType());

        importedTypes.add(parameterType);
        method.addParameter(new Parameter(parameterType, "entity")); //$NON-NLS-1$

        context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

        interfaze.addImportedTypes(importedTypes);
        interfaze.addMethod(method);
    }

    /**
     * @author DaiJiangGuo
     * @data 2015年5月11日 下午11:01:45
     * @param interfaze
     */
    private void addFindByPkMethod(Interface interfaze, IntrospectedTable introspectedTable) {
        Set<FullyQualifiedJavaType> importedTypes = new TreeSet<FullyQualifiedJavaType>();
        Method method = new Method();

        method.setVisibility(JavaVisibility.PUBLIC);
        method.setReturnType(new FullyQualifiedJavaType(introspectedTable.getBaseRecordType()));
        method.setName(apc.serviceMethod_findByPk);

        List<IntrospectedColumn> pkCols = introspectedTable.getPrimaryKeyColumns();
        for(IntrospectedColumn pk : pkCols){
            FullyQualifiedJavaType paramPk = pk.getFullyQualifiedJavaType();
            importedTypes.add(paramPk);
            method.addParameter(new Parameter(paramPk, pk.getJavaProperty()));
        }

        context.getCommentGenerator().addGeneralMethodComment(method,
                introspectedTable);

        interfaze.addImportedTypes(importedTypes);
        interfaze.addMethod(method);
    }


}
